package ar.com.fiuba.RulesMgr.rules;

import java.util.List;

import ar.com.fiuba.RulesMgr.connectors.Connector;
import ar.com.fiuba.RulesMgr.exceptions.InvalidRuleException;
import ar.com.fiuba.RulesMgr.validationModes.ValidationMode;

/**
 * Class that represents the combination of two rules with a logical connector.
 * 
 */
public class CompositeRule extends GenericRule {

	private GenericRule leftRule;

	private GenericRule rightRule;

	private Connector connector;

	/**
	 * Constructor.
	 * 
	 * @param ruleName
	 *            name for the rule.
	 * @param leftRule
	 *            first rule to be applied.
	 * @param rightRule
	 *            second rule to be applied.
	 * @param connector
	 *            connector to connect both rules.
	 * @throws InvalidRuleException
	 *             if an invalid parameter is provided, such as a null value.
	 */
	public CompositeRule(String ruleName, GenericRule leftRule, GenericRule rightRule, Connector connector)
			throws InvalidRuleException {

		if (ruleName == null)
			throw new InvalidRuleException("The Rule hasn't got a Name.");
		this.ruleName = ruleName;

		if (connector == null)
			throw new InvalidRuleException("The Rule hasn't got a connector.");
		this.connector = connector;

		if (leftRule == null)
			throw new InvalidRuleException("The left child of the CompositeRule is null.");
		this.leftRule = leftRule;

		if (rightRule == null)
			throw new InvalidRuleException("The right child of the CompositeRule is null.");
		this.rightRule = rightRule;

	}

	/**
	 * {@link GenericRule#validateWithMode(ValidationMode, List)}
	 */
	@Override
	public Boolean validateWithMode(ValidationMode validationMode, List<Object> objects) {
		return modifier.apply(validationMode.validate(this, objects));
	}

	/**
	 * {@link GenericRule#validate(List)}
	 */
	@Override
	public final Boolean validate(List<Object> objects) {
		return connector.evaluate(leftRule.validate(objects), rightRule.validate(objects));
	}

	public Connector getConnector() {
		return connector;
	}

	public GenericRule getLeftRule() {
		return leftRule;
	}

	public GenericRule getRightRule() {
		return rightRule;
	}

}
